﻿// Tetris.cpp : 定义应用程序的入口点。
//

/*
记录于2016-5-29 星期日    由于闪屏过于显眼，采用双缓冲

*/

#include "stdafx.h"
#include "Tetris.h"
#include "windows.h"
#include <mmsystem.h>//包含与多媒体有关的接口
#pragma comment(lib, "WINMM.LIB")
#define MAX_LOADSTRING 100

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);// 注册窗口类
BOOL                InitInstance(HINSTANCE, int); //初始化应用程序
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);//窗口消息处理函数
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);//对话框处理

// 全局变量:
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名

int APIENTRY _tWinMain(HINSTANCE hInstance,//当前实例句柄
	HINSTANCE hPrevInstance,//父窗口句柄
	LPTSTR    lpCmdLine,//指向传递给应用程序的命令行参数的指针
	int       nCmdShow)//指定程序窗口如何显示
{
	init_game();//初始化游戏
	UNREFERENCED_PARAMETER(hPrevInstance);//展开传递的参数或表达式
	UNREFERENCED_PARAMETER(lpCmdLine);//避免编译器关于未引用参数的警告

	// TODO: 在此放置代码。
	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_TETRIS, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);//注册窗口类

	// 执行应用程序初始化:
	if (!InitInstance(hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TETRIS));

	// 主消息循环:
	while (1)
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))//查询消息队列，从消息队列中取出消息
		{
			TranslateMessage(&msg);//将消息的虚拟键转化为字符消息
			DispatchMessage(&msg);//将消息传送到指定窗口函数
			if (msg.message == WM_QUIT)////若消息是退出，则终止程序
			{
				break;
			}
		}
		else
		{
			if ((GAME_STATE & 2) != 0)
			{
				tCur = GetTickCount();//返回从操作系统启动所经过的毫秒数
				if (tCur - tPre>g_speed)//超过反应时间
				{

					int flag = CheckValide(curPosX, curPosY + 1, bCurTeris);//判断下一行的情况
					if (flag == 1)//下降一行
					{
						curPosY++;//方块y坐标加1
						tPre = tCur;//重新计算反应时间
						HWND hWnd = GetActiveWindow();
						//获得与调用线程的消息队列相关的活动窗口的窗口句柄
						InvalidateRect(hWnd, &rc_left, FALSE);
						//向指定的窗体更新区域添加一个矩形，然后窗口客户区域的这一部分将被重新绘制
						InvalidateRect(hWnd, &rc_right_top, FALSE);
					}
					else if (flag == -2)//方块到底
					{
						g_speed = t_speed;//重置速度
						fillBlock();////将方块填充给矩形
						checkComplite();//查看是否能消去这一行
						setRandomT();//随机产生新的方块
						curPosX = (NUM_X - 4) >> 1; //设置方块的坐标x
						curPosY = 0;//设置方块的坐标y
						HWND hWnd = GetActiveWindow();
						//获得与调用线程的消息队列相关的活动窗口的窗口句柄
						InvalidateRect(hWnd, &rc_main, FALSE);//刷新矩形区域
					}
					else if (flag == -3)//放不下方块（游戏失败）
					{
						HWND hWnd = GetActiveWindow();
						//获得与调用线程的消息队列相关的活动窗口的窗口句柄
						if (MessageBox(hWnd, L"胜败乃兵家常事，菜鸡请重新来过", L":时光机", MB_YESNO) == IDYES)
						//消息提示，游戏结束
						{
							init_game();//重新开始
						}
						else
						{
							break;//退出
						}
					}
				}
			}
		}
	}

	return (int)msg.wParam;
}


//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时，才需要此函数及其用法。调用此函数十分重要，
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;//定义窗口类对象

	wcex.cbSize = sizeof(WNDCLASSEX);//窗口大小
	wcex.style = CS_HREDRAW | CS_VREDRAW;//风格
	wcex.lpfnWndProc = WndProc;//消息过程处理函数
	wcex.cbClsExtra = 0;//窗口类额外字节数
	wcex.cbWndExtra = 0;//窗口实例额外字节数
	wcex.hInstance = hInstance;//当前实例句柄
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TETRIS));//应用程序的图标为默认图标
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);//箭头光标
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//背景
	wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TETRIS);//把一个数字类型转换成指针类型的宏
	wcex.lpszClassName = szWindowClass;//设置窗口类名
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));//窗口标题栏的图标为默认图标

	return RegisterClassEx(&wcex);//返回注册窗口
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中，我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;

	hInst = hInstance; // 将实例句柄存储在全局变量中

	hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,//创建窗口
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	//WS_OVERLAPPEDWINDOW：多种窗口类型的组合
	//CW_USEDEFAULT：窗口的大小位置等为默认值
	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);//显示窗口
	UpdateWindow(hWnd);//更新窗口

	return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;//该结构体包含了某应用程序用来绘制它所拥有的窗口客户区所需要的信息
	HDC hdc;//设备环境句柄
	int nWinx, nWiny, nClientX, nClientY;
	int posX, posY;
	RECT rect;//用来存储成对出现的参数
	HMENU hSysmenu;//菜单窗口的句柄
	switch (message)
	{
	case WM_CREATE://当一个应用程序请求创建窗口时发送此消息

		GetWindowRect(hWnd, &rect);//窗口的位置
		nWinx = 530;//窗口宽度
		nWiny = 680;//窗口高度
		posX = GetSystemMetrics(SM_CXSCREEN);//获取屏幕宽度
		posY = GetSystemMetrics(SM_CYSCREEN);//获取屏幕高度
		posX = (posX - nWinx) >> 1;//计算居中放置的X位置
		posY = (posY - nWiny) >> 1;//计算居中放置的Y位置
		GetClientRect(hWnd, &rect);//获取窗口客户区的大小
		nClientX = rect.right - rect.left;//用户区域宽度
		nClientY = rect.bottom - rect.top;//用户区域高度

		MoveWindow(hWnd, posX, posY, 530, 680, TRUE); //改变指定窗口的位置和大小
		hSysmenu = GetSystemMenu(hWnd, false);//允许应用程序为复制或修改而访问窗口菜单
		AppendMenu(hSysmenu, MF_SEPARATOR, 0, NULL);//添加一个新菜单
		//AppendMenu(hSysmenu, 0, IDM_DIFF, L"难度选择");
		selectDiffculty(hWnd, 1);//难度选择
		break;
	case WM_COMMAND://点击菜单、按钮、下拉列表框等控件时触发
		wmId = LOWORD(wParam); //获取低位字节
		wmEvent = HIWORD(wParam);//获取高位字节
		// 分析菜单选择:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			//创建一个基于模板资源的模态对话框
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);//退出程序
			break;/*
		case ID_dif1:
			selectDiffculty(hWnd, 1);
			break;
		case ID_dif2:
			selectDiffculty(hWnd, 2);
			break;
		case ID_dif3:
			selectDiffculty(hWnd, 3);
			break;
		case ID_LAYOUT1:
			selectLayOut(hWnd, 1);
			break;
		case ID_LAYOUT2:
			selectLayOut(hWnd, 2);
			break;*/
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);//缺省处理函数
		}
		break;
	case WM_KEYDOWN://键盘消息
		hdc = GetDC(hWnd);
		//检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄
		InvalidateRect(hWnd, NULL, false); 
		//向指定的窗体更新区域添加一个矩形，然后窗口客户区域的这一部分将被重新绘制
		switch (wParam)
		{
		case VK_LEFT:
			curPosX--;
			if (CheckValide(curPosX, curPosY, bCurTeris) != 1)
			{
				curPosX++;//右移
			}
			break;
		case VK_RIGHT:
			curPosX++;
			if (CheckValide(curPosX, curPosY, bCurTeris) != 1)
			{
				curPosX--;//左移
			}
			break;
		case VK_UP:
			RotateTeris(bCurTeris);//改变形状
			break;
		case VK_DOWN://加速到底
			if (g_speed == t_speed)
				g_speed = 10;
			else
				g_speed = t_speed;
			//outPutBoxInt(g_speed);
			break;
		case 'W':
			RotateTeris(bCurTeris);
			break;
		case 'A':
			curPosX--;
			if (CheckValide(curPosX, curPosY, bCurTeris) != 1)
			{
				curPosX++;
			}
			break;
		case 'D':
			curPosX++;
			if (CheckValide(curPosX, curPosY, bCurTeris) != 1)
			{
				curPosX--;
			}
			break;

		case 'S':
			if (g_speed == t_speed)
				g_speed = 10;
			else
				g_speed = t_speed;
			//outPutBoxInt(g_speed);
			break;
		default:
			break;
		}

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		DrawBackGround(hdc);///绘制背景
		EndPaint(hWnd, &ps);//停止绘制
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//退出
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);//缺省处理函数
	}
	return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam)); 
			//清除一个模态对话框, 并使系统中止对对话框的任何处理的函数
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}


void drawBlocked(HDC mdc)//绘制当前已经存在砖块的区域
{
	int i, j;

	HBRUSH hBrush = (HBRUSH)CreateSolidBrush(RGB(255, 255, 0));////画刷句柄，黄色

	SelectObject(mdc, hBrush);
	//选择一对象到指定的设备上下文环境中，该新对象替换先前的相同类型的对象

	for (i = 0; i<NUM_Y; i++)
	{
		for (j = 0; j<NUM_X; j++)
		{
			if (g_hasBlocked[i][j])
			{
				Rectangle(mdc, BORDER_X + j*BLOCK_SIZE, BORDER_Y + i*BLOCK_SIZE,
					BORDER_X + (j + 1)*BLOCK_SIZE, BORDER_Y + (i + 1)*BLOCK_SIZE
				);//绘画矩形的函数
			}
		}
	}
	DeleteObject(hBrush);
	//删除一个逻辑笔、画笔、字体、位图、区域或者调色板，释放所有与该对象有关的系统资源
}

int CheckValide(int startX, int startY, BOOL bTemp[4][4])//给定一个矩阵，查看是否合法
{
	int i, j;
	for (i = 3; i >= 0; i--)
	{
		for (j = 3; j >= 0; j--)
		{
			if (bTemp[i][j])
			{
				if (j + startX<0 || j + startX >= NUM_X)
				{
					return -1;
				}
				if (i + startY >= NUM_Y)
				{
					return -2;
				}
				if (g_hasBlocked[i + startY][j + startX])
				{
					//outPutBoxInt(j+startY);
					if (curPosY == 0)
					{
						return -3;
					}
					return -2;
				}
			}
		}
	}
	//MessageBox(NULL,L"这里",L"as",MB_OK);
	//outPutBoxInt(curPosY);
	return 1;
}

void checkComplite()
{
	int i, j, k, count = 0;
	for (i = 0; i<NUM_Y; i++)
	{
		bool flag = true;
		for (j = 0; j<NUM_X; j++)
		{
			if (!g_hasBlocked[i][j])//有一个为空时，不能消去该行
			{
				flag = false;
			}
		}
		if (flag)//消去后每行下移
		{
			count++;
			for (j = i; j >= 1; j--)
			{
				for (k = 0; k<NUM_X; k++)
				{
					g_hasBlocked[j][k] = g_hasBlocked[j - 1][k];
				}

			}
			drawCompleteParticle(i);//做出消去的效果
			Sleep(300);//暂停300ms

			PlaySound(_T("coin.wav"), NULL, SND_FILENAME | SND_ASYNC);//播放消去音效
		}
	}
	GAME_SCORE += int(count*1.5);//单行+1分，两行+3分，三行+4分，四行6分
}



VOID outPutBoxInt(int num)//自定义的弹窗函数，用于调试
{
	TCHAR szBuf[1024];
	LPCTSTR str = TEXT("%d");
	wsprintf(szBuf, str, num);
	// 将一系列的字符和数值输入到缓冲区。输出缓冲区里的的值取决于格式说明符（即"%"）
	MessageBox(NULL, szBuf, L"aasa", MB_OK);//显示消息框
}

VOID outPutBoxString(TCHAR str[1024])//自定义的弹窗函数
{
	TCHAR szBuf[1024];
	LPCTSTR cstr = TEXT("%s");
	wsprintf(szBuf, cstr, str);
	MessageBox(NULL, szBuf, L"aasa", MB_OK);
}



//设置随机方块形状
void setRandomT()
{
	int rd_start = RandomInt(0, sizeof(state_teris) / sizeof(state_teris[0]));
	int rd_next = RandomInt(0, sizeof(state_teris) / sizeof(state_teris[0]));
	//outPutBoxInt(rd_start);
	//outPutBoxInt(rd_next);
	//outPutBoxInt(rd_start);
	if (GAME_STATE == 0)
	{
		GAME_STATE = GAME_STATE | 0x0001;
		//outPutBoxInt(GAME_STATE);
		memcpy(bCurTeris, state_teris[rd_start], sizeof(state_teris[rd_start]));//内存拷贝函数
		memcpy(bNextCurTeris, state_teris[rd_next], sizeof(state_teris[rd_next]));
	}
	else
	{
		memcpy(bCurTeris, bNextCurTeris, sizeof(bNextCurTeris));
		memcpy(bNextCurTeris, state_teris[rd_next], sizeof(state_teris[rd_next]));
	}

}

//游戏初始化
void init_game()
{
	GAME_SCORE = 0;
	setRandomT();//随机生成一个方块等待下一次下落
	curPosX = (NUM_X - 4) >> 1;//初始坐标
	curPosY = 0;


	memset(g_hasBlocked, 0, sizeof(g_hasBlocked));//用于内存空间初始化
	rc_left.left = 0;
	rc_left.right = SCREEN_LEFT_X;
	rc_left.top = 0;
	rc_left.bottom = SCREEN_Y;

	rc_right.left = rc_left.right + BORDER_X;
	rc_right.right = 180 + rc_right.left;
	rc_right.top = 0;
	rc_right.bottom = SCREEN_Y;

	rc_main.left = 0;
	rc_main.right = SCREEN_X;
	rc_main.top = 0;
	rc_main.bottom = SCREEN_Y;

	rc_right_top.left = rc_right.left;
	rc_right_top.top = rc_right.top;
	rc_right_top.right = rc_right.right;
	rc_right_top.bottom = (rc_right.bottom) / 2;

	rc_right_bottom.left = rc_right.left;
	rc_right_bottom.top = rc_right_top.bottom + BORDER_Y;
	rc_right_bottom.right = rc_right.right;
	rc_right_bottom.bottom = rc_right.bottom;

	g_speed = t_speed = 1000 - GAME_DIFF * 280;
}

//到达底部后填充矩阵
void fillBlock()
{
	int i, j;
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (bCurTeris[i][j])
			{
				g_hasBlocked[curPosY + i][curPosX + j] = 1;
			}
		}
	}
}

//旋转矩阵
void RotateTeris(BOOL bTeris[4][4])
{
	BOOL bNewTeris[4][4];
	int x, y;
	for (x = 0; x<4; x++)
	{
		for (y = 0; y<4; y++)
		{
			bNewTeris[x][y] = bTeris[3 - y][x];//旋转
			//逆时针：
			//bNewTeris[x][y] = bTeris[y][3-x];
		}
	}
	if (CheckValide(curPosX, curPosY, bNewTeris) == 1)
	{
		memcpy(bTeris, bNewTeris, sizeof(bNewTeris));//成功变换后的保存形状
	}

}

int RandomInt(int _min, int _max)
{
	srand((rd_seed++) % 65532 + GetTickCount());
	return _min + rand() % (_max - _min);
}

VOID DrawTeris(HDC mdc)
{

	int i, j;
	HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);//画笔句柄
	HBRUSH hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);//检索预定义的备用笔、刷子、字体或者调色板的句柄
	SelectObject(mdc, hPen); //选择一对象到指定的设备上下文环境中，该新对象替换先前的相同类型的对象
	SelectObject(mdc, hBrush);
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (bCurTeris[i][j])
			{
				Rectangle(mdc, (j + curPosX)*BLOCK_SIZE + BORDER_X, (i + curPosY)*BLOCK_SIZE + BORDER_Y, (j + 1 + curPosX)*BLOCK_SIZE + BORDER_X, (i + 1 + curPosY)*BLOCK_SIZE + BORDER_Y);
			    //画一个矩形，可以用当前的画笔画矩形轮廓，用当前画刷进行填充
			}
		}
	}
	drawBlocked(mdc);
	DeleteObject(hPen);
	DeleteObject(hBrush);
}
//绘制背景
VOID DrawBackGround(HDC hdc)
{

	HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);//检索预定义的备用笔、刷子、字体或者调色板的句柄
	HDC mdc = CreateCompatibleDC(hdc);//创建一个与指定设备兼容的内存设备上下文环境
	HBITMAP hBitmap = CreateCompatibleBitmap(hdc, SCREEN_X, SCREEN_Y);//建立一个与屏幕显示兼容的位图

	SelectObject(mdc, hBrush);//将位图选入到内存显示设备中
	SelectObject(mdc, hBitmap);

	HBRUSH hBrush2 = (HBRUSH)GetStockObject(WHITE_BRUSH);
	FillRect(mdc, &rc_main, hBrush2);//用指定的画刷填充矩形
	Rectangle(mdc, rc_left.left + BORDER_X, rc_left.top + BORDER_Y, rc_left.right, rc_left.bottom);
	Rectangle(mdc, rc_right.left + BORDER_X, rc_right.top + BORDER_Y, rc_right.right, rc_right.bottom);
	DrawTeris(mdc);
	drawNext(mdc);
	drawScore(mdc);
	::BitBlt(hdc, 0, 0, SCREEN_X, SCREEN_Y, mdc, 0, 0, SRCCOPY);
	DeleteObject(hBrush);
	DeleteDC(mdc);
	DeleteObject(hBitmap);
	DeleteObject(hBrush2);


	//  int x,y;
	//  HPEN hPen = (HPEN)GetStockObject(NULL_PEN);
	//  HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
	//  SelectObject(hdc,hPen);
	//  SelectObject(hdc,hBrush);
	//  for (x = 0;x<NUM_X;x++)
	//  {
	//      for(y=0;y<NUM_Y;y++)
	//      {
	//          Rectangle(hdc,BORDER_X+x*BLOCK_SIZE,BORDER_Y+y*BLOCK_SIZE,
	//              BORDER_X+(x+1)*BLOCK_SIZE,
	//              BORDER_Y+(y+1)*BLOCK_SIZE);
	//      }
	//  }
}

void drawNext(HDC hdc)//绘制下一个将要掉落的方块
{
	int i, j;
	HBRUSH hBrush = (HBRUSH)CreateSolidBrush(RGB(0, 188, 0)); //创建背景刷子
	SelectObject(hdc, hBrush);
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (bNextCurTeris[i][j])
			{
				Rectangle(hdc, rc_right_top.left + BLOCK_SIZE*(j + 1), rc_right_top.top + BLOCK_SIZE*(i + 1), rc_right_top.left + BLOCK_SIZE*(j + 2), rc_right_top.top + BLOCK_SIZE*(i + 2));
			}
		}
	}
	HFONT hFont = CreateFont(30, 0, 0, 0, FW_THIN, 0, 0, 0, UNICODE, 0, 0, 0, 0, L"微软雅黑");
	SelectObject(hdc, hFont);
	SetBkMode(hdc, TRANSPARENT);
	SetBkColor(hdc, RGB(255, 255, 0));
	RECT rect;
	rect.left = rc_right_top.left + 40;
	rect.top = rc_right_top.bottom - 150;
	rect.right = rc_right_top.right;
	rect.bottom = rc_right_top.bottom;
	DrawTextW(hdc, TEXT("下一个"), _tcslen(TEXT("下一个")), &rect, 0);
	DeleteObject(hFont);
	DeleteObject(hBrush);
}

void drawScore(HDC hdc)//绘制分数
{
	HFONT hFont = CreateFont(30, 0, 0, 0, FW_THIN, 0, 0, 0, UNICODE, 0, 0, 0, 0, L"微软雅黑");
	SelectObject(hdc, hFont);
	SetBkMode(hdc, TRANSPARENT);
	SetBkColor(hdc, RGB(255, 255, 0));
	RECT rect;
	rect.left = rc_right_bottom.left;
	rect.top = rc_right_bottom.top;
	rect.right = rc_right_bottom.right;
	rect.bottom = rc_right_bottom.bottom;
	TCHAR szBuf[30];
	LPCTSTR cstr = TEXT("当前难度：%d");
	wsprintf(szBuf, cstr, GAME_DIFF);
	DrawTextW(hdc, szBuf, _tcslen(szBuf), &rect, DT_CENTER | DT_VCENTER);

	RECT rect2;
	rect2.left = rc_right_bottom.left;
	rect2.top = rc_right_bottom.bottom / 2 + 100;
	rect2.right = rc_right_bottom.right;
	rect2.bottom = rc_right_bottom.bottom;
	TCHAR szBuf2[30];
	LPCTSTR cstr2 = TEXT("得分：%d");
	wsprintf(szBuf2, cstr2, GAME_SCORE);
	//outPutBoxInt(sizeof(szBuf));
	DrawTextW(hdc, szBuf2, _tcslen(szBuf2), &rect2, DT_CENTER | DT_VCENTER);

	DeleteObject(hFont);
}

int selectDiffculty(HWND hWnd, int diff)
{
	TCHAR szBuf2[30];
	LPCTSTR cstr2 = TEXT("确认选择难度 %d 吗？");
	wsprintf(szBuf2, cstr2, diff);
	if (MessageBox(hWnd, szBuf2, L"难度选择", MB_YESNO) == IDYES)
	{
		GAME_DIFF = diff;
		InvalidateRect(hWnd, &rc_right_bottom, false);
		GAME_STATE |= 2;
		init_game();
		return GAME_DIFF;
	}
	return -1;
}

int selectLayOut(HWND hWnd, int layout)//选择布局
{
	NUM_X = 10 * layout;
	NUM_Y = 20 * layout;
	BLOCK_SIZE = 30 / layout;
	GAME_STATE |= 2;
	InvalidateRect(hWnd, &rc_right_bottom, false);
	init_game();
	return layout;
}

void drawCompleteParticle(int line)
{
	HWND hWnd = GetActiveWindow();
	HDC hdc = GetDC(hWnd);
	HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
	HPEN hPen = (HPEN)CreatePen(PS_DOT, 1, RGB(255, 255, 0));
	SelectObject(hdc, hBrush);
	SelectObject(hdc, hPen);
	Rectangle(hdc, BORDER_X,
		BORDER_Y + line*BLOCK_SIZE,
		BORDER_X + NUM_X*BLOCK_SIZE,
		BORDER_Y + BLOCK_SIZE*(1 + line));
	DeleteObject(hBrush);
	DeleteObject(hPen);
}